home *** CD-ROM | disk | FTP | other *** search
- #
- # This file is for inclusion with
- # . /lib/cryptsetup/cryptdisks.functions
- # and should not be executed directly.
-
- PATH="/sbin:/bin"
- TABFILE="/etc/crypttab"
- CRYPTDISKS_ENABLE="Yes"
-
- #set -x
-
- # Sanity checks
- [ -x /sbin/cryptsetup ] || exit 0
- [ -f "$TABFILE" ] || exit 0
-
- . /lib/lsb/init-functions
-
- if [ -r /etc/default/cryptdisks ]; then
- . /etc/default/cryptdisks
- fi
-
- MOUNT="$CRYPTDISKS_MOUNT"
-
- LOUD=""
-
- # Parses the option field from the crypttab file
- parse_opts () {
- local opts opt IFS PARAM VALUE
-
- # Strip comments - https://bugs.launchpad.net/bugs/185380
- opts=$(echo -n $1 | sed 's/ *#.*//')
- PARAMS=""
- CHECK=""
- CHECKARGS=""
- PRECHECK=""
- TRIES="3"
- TMPFS=""
- MAKESWAP=""
- USELUKS=""
- KEYSCRIPT=""
- IGNORE=""
-
- # Parse the options field, convert to cryptsetup parameters
- # and construct the command line
- IFS=','
- for opt in $opts; do
- PARAM=$(echo "$opt" | sed 's/=.*//')
- VALUE=$(echo "$opt" | sed '/=/!d;s/^.*=//')
-
- case "$PARAM" in
- readonly)
- PARAMS="$PARAMS -r"
- ;;
- cipher)
- if [ -z "$VALUE" ]; then
- log_warning_msg "$dst: no value for cipher option, skipping"
- return 1
- fi
- PARAMS="$PARAMS -c $VALUE"
- ;;
- size)
- if [ -z "$VALUE" ] || echo "$VALUE" | grep -q "^[[:digit:]]\+$" && [ "$VALUE" -gt 0 ]; then
- PARAMS="$PARAMS -s $VALUE"
- else
- log_warning_msg "$dst: option size used with an incorrect argument, skipping"
- return 1
- fi
- ;;
- hash)
- if [ -z "$VALUE" ]; then
- log_warning_msg "$dst: no value for hash option, skipping"
- return 1
- fi
- PARAMS="$PARAMS -h $VALUE"
- ;;
- offset)
- if [ -z "$VALUE" ]; then
- log_warning_msg "$dst: no value for offset option, skipping"
- return 1
- fi
- PARAMS="$PARAMS -o $VALUE"
- ;;
- skip)
- if [ -z "$VALUE" ]; then
- log_warning_msg "$dst: no value for skip option, skipping"
- return 1
- fi
- PARAMS="$PARAMS -p $VALUE"
- ;;
- verify)
- PARAMS="$PARAMS -y"
- ;;
- check)
- if [ -z "$VALUE" ]; then
- VALUE="$CRYPTDISKS_CHECK"
- fi
- if [ -x "$VALUE" ]; then
- CHECK="$VALUE"
- elif [ -x "/lib/cryptsetup/checks/$VALUE" ]; then
- CHECK="/lib/cryptsetup/checks/$VALUE"
- else
- log_warning_msg "check $VALUE is not an executable script, skipping"
- return 1
- fi
- ;;
- checkargs)
- if [ -n "$VALUE" ]; then
- CHECKARGS="$VALUE"
- fi
- ;;
- precheck)
- if [ -z "$VALUE" ]; then
- VALUE="$CRYPTDISKS_PRECHECK"
- fi
- if [ -x "$VALUE" ]; then
- PRECHECK="$VALUE"
- elif [ -x "/lib/cryptsetup/checks/$VALUE" ]; then
- PRECHECK="/lib/cryptsetup/checks/$VALUE"
- else
- log_warning_msg "precheck $VALUE is not an executable script, skipping"
- return 1
- fi
- ;;
- tries)
- if echo "$VALUE" | grep -q "^[[:digit:]]\+$" && [ "$VALUE" -gt 0 ]; then
- TRIES="$VALUE"
- else
- log_warning_msg "$dst: option tries used with an incorrect argument - forced to $TRIES"
- fi
- ;;
- swap)
- MAKESWAP="yes"
- SWCHECK="/lib/cryptsetup/checks/un_vol_id"
- SWCHECKARGS="swap"
- ;;
- tmp)
- if [ -z "$VALUE" ]; then
- TMPFS="ext2"
- else
- TMPFS="$VALUE"
- fi
- ;;
- luks)
- USELUKS="yes"
- ;;
- noearly)
- if [ "$INITSTATE" = "early" ]; then
- IGNORE="yes"
- fi
- ;;
- noauto)
- if [ -n "$INITSTATE" ]; then
- IGNORE="yes"
- fi
- ;;
- loud)
- LOUD="yes"
- ;;
- keyscript)
- if [ -n "$KEYSCRIPT" ]; then
- log_warning_msg "$dst: multiple key decryption options are not allowed together, skipping"
- return 1
- elif [ -x "$VALUE" ]; then
- KEYSCRIPT="$VALUE"
- elif [ -x "/lib/cryptsetup/scripts/$VALUE" ]; then
- KEYSCRIPT="/lib/cryptsetup/scripts/$VALUE"
- elif [ -z "$VALUE" ]; then
- log_warning_msg "$dst: no value for keyscript option, skipping"
- return 1
- else
- log_warning_msg "script $VALUE is not an executable script, skipping"
- return 1
- fi
- ;;
- esac
- done
-
- return 0
- }
-
- # Set up loopback devices
- lo_setup () {
- #local loopdev
-
- if [ ! -f "$src" ]; then
- return 0
- fi
-
- if [ ! -x /sbin/losetup ]; then
- return 1
- fi
-
- if ! grep -q "[[:space:]]loop$" /proc/devices; then
- modprobe -qb loop > /dev/null 2>&1 || return 1
- fi
-
- loopdev=$(losetup -f 2> /dev/null) || return 1
-
- losetup "$loopdev" "$src" || return 1
- src="$loopdev"
- return 0
- }
-
- rm_lo_setup () {
- if [ ! -f "$src" ]; then
- return 0
- fi
-
- if [ -n "$loopdev" ]; then
- losetup -d "$loopdev" || return 1
- fi
- return 0
- }
-
- # Sanity check for keys
- check_key () {
- local GMODE OMODE OWNER GROUP
-
- # If the keyscript option is set, the "key" is just an argument to
- # the keyscript and not necessarily a file
- if [ -n "$KEYSCRIPT" ]; then
- return 0
- fi
-
- if [ -z "$key" ] || [ "$key" = "none" ]; then
- key=""
- return 0
- fi
-
- if [ ! -e "$key" ]; then
- log_warning_msg "$dst: keyfile not found"
- return 1
- fi
-
- # stat is unfortunately in /usr/bin...
- OMODE=$(ls -l "$key" | sed 's/[[:space:]].*//;s/^.\{7\}//')
- GMODE=$(ls -l "$key" | sed 's/[[:space:]].*//;s/^.\{4\}\(.\{3\}\).*/\1/')
- GROUP=$(ls -l "$key" | sed 's/^.\{11\}[^[:space:]]* [^[:space:]]* \([^[:space:]]*\).*/\1/')
- # regex needs to work if keyfile has xattrs - https://launchpad.net/bugs/231339
- OWNER=$(ls -l "$key" | sed 's/^.\{10\}[+]\?.[^[:space:]]* \([^[:space:]]*\).*/\1/')
-
- # LUKS requires a persistent key, /dev/*random is not supported
- if [ "$USELUKS" = "yes" ] && [ "$key" != "${key%random}" ]; then
- log_warning_msg "$dst: LUKS does not work with random data as key"
- return 1
- fi
-
- # Check owner
- if [ "$OWNER" != "root" ]; then
- log_warning_msg "$dst: INSECURE OWNER FOR $key, see /usr/share/doc/cryptsetup/README.Debian."
- fi
-
- # If key is random, we're done
- if [ "$key" != "${key%random}" ]; then
- return 0
- fi
-
- # Check group and other permissions
- if [ "$OMODE" != "---" ] || [ "$GROUP" != "root" ] && [ "$GMODE" != "---" ]; then
- log_warning_msg "$dst: INSECURE MODE FOR $key, see /usr/share/doc/cryptsetup/README.Debian."
- fi
-
- return 0
- }
-
- # Setup a luks mapping
- do_luks () {
- local tried keyscriptarg
- tried=0
- keyscriptarg=""
-
- if ! cryptsetup isLuks "$src" >/dev/null 2>&1; then
- log_warning_msg "$dst: device '$src' is not a LUKS partition, skipping"
- return 1
- fi
-
- if [ -n "$KEYSCRIPT" ]; then
- # keyscript => "key" is just an argument to the keyscript
- keyscriptarg="$key"
- key="-"
- elif [ -z "$key" ]; then
- # no keyscript, no key => password
- keyscriptarg="Enter passphrase to unlock the disk $src ($dst): "
- key="-"
- KEYSCRIPT="/lib/cryptsetup/askpass"
- elif [ "$key" != "${key%/dev/*}" ]; then
- # no keyscript, device key => special treatment
- keyscriptarg=""
- key="$key"
- KEYSCRIPT=""
- else
- # no keyscript, key => file input
- keyscriptarg="$key"
- key="-"
- KEYSCRIPT="cat"
- fi
-
- PARAMS="$PARAMS --key-file=$key"
-
- while [ "$tried" -lt "$TRIES" ]; do
- if [ -n "$KEYSCRIPT" ]; then
- if "$KEYSCRIPT" "$keyscriptarg" | cryptsetup $PARAMS luksOpen "$src" "$dst"; then
- break
- fi
- else
- if cryptsetup $PARAMS luksOpen "$src" "$dst"; then
- break
- fi
- fi
-
- tried=$(( $tried + 1 ))
- if [ "$tried" -ge "$TRIES" ]; then
- return 1
- fi
- done
-
- if [ -n "$CHECK" ] && ! "$CHECK" "/dev/mapper/$dst" $CHECKARGS; then
- log_warning_msg "$dst: the check for '/dev/mapper/$dst' failed"
- cryptsetup luksClose "$dst"
- return 1
- fi
-
- return 0
- }
-
- # Setup a regular mapping
- do_noluks () {
- local pre_out tried keyscriptarg
- tried=0
- keyscriptarg=""
-
- if [ -z "$PRECHECK" ]; then
- PRECHECK="/lib/cryptsetup/checks/un_vol_id"
- fi
-
- if ! pre_out=$("$PRECHECK" "$src" 2> /dev/null) && \
- [ "$MAKESWAP" != "yes" ] && \
- ! /lib/cryptsetup/checks/vol_id "$src" swap >/dev/null; then
- log_warning_msg "$dst: the precheck for '$src' failed: $pre_out"
- return 1
- fi
-
- if [ -n "$KEYSCRIPT" ]; then
- # keyscript => "key" is just an argument to the keyscript
- keyscriptarg="$key"
- key="-"
- elif [ -z "$key" ]; then
- # no keyscript, no key => password
- keyscriptarg="Enter passphrase to unlock the disk $src ($dst): "
- key="-"
- KEYSCRIPT="/lib/cryptsetup/askpass"
- else
- # no keyscript, key => file input
- keyscriptarg=""
- key="$key"
- KEYSCRIPT=""
- fi
-
- PARAMS="$PARAMS --key-file=$key"
-
- while [ "$tried" -lt "$TRIES" ]; do
- if [ -n "$KEYSCRIPT" ]; then
- "$KEYSCRIPT" "$keyscriptarg" | cryptsetup $PARAMS create "$dst" "$src"
- else
- cryptsetup $PARAMS create "$dst" "$src"
- fi
-
- if [ -z "$CHECK" ] || "$CHECK" "/dev/mapper/$dst" $CHECKARGS; then
- break
- else
- log_warning_msg "$dst: the check for '/dev/mapper/$dst' failed - maybe the password is wrong"
- cryptsetup remove "$dst"
- fi
-
- tried=$(( $tried + 1 ))
- if [ "$tried" -ge "$TRIES" ]; then
- return 1
- fi
- done
-
- return 0
- }
-
- # Premounts file systems
- mount_fs () {
- local point
- MOUNTED=""
-
- for point in $MOUNT; do
- if mount "$point" >/dev/null; then
- MOUNTED="$MOUNTED $point"
- fi
- done
- }
-
- # Postunmounts file systems
- umount_fs () {
- local point
-
- for point in $MOUNTED; do
- umount "$point" >/dev/null
- done
- }
-
- # Prepares swap partitions using random keys
- do_swap () {
- local swap_out
-
- if [ "$MAKESWAP" != "yes" ] || [ ! -b "/dev/mapper/$dst" ]; then
- return 0
- fi
-
- if swap_out=$(/lib/cryptsetup/checks/un_vol_id "/dev/mapper/$dst" 2> /dev/null) || \
- /lib/cryptsetup/checks/vol_id "/dev/mapper/$dst" swap > /dev/null 2>&1; then
- mkswap "/dev/mapper/$dst" > /dev/null 2>&1
- else
- log_warning_msg "$dst: the check for '/dev/mapper/$dst' failed. /dev/mapper/$dst contains data: $swap_out"
- do_close
- return 1
- fi
-
- return 0
- }
-
- # Prepares tmp partitions using random keys
- do_tmp () {
- if [ "x$TMPFS" = "x" ] || [ ! -b "/dev/mapper/$dst" ]; then
- return 0
- fi
-
- mkfs -t $TMPFS -q "/dev/mapper/$dst" > /dev/null 2>&1 || return 1
- mount -t $TMPFS "/dev/mapper/$dst" /tmp || return 1
- chmod 1777 /tmp
- umount /tmp
- return 0
- }
-
- # Removes a mapping
- do_close () {
- local found IFS opt
-
- found="no"
- IFS=','
- for opt in $opts; do
- if [ "$opt" = "luks" ]; then
- found="yes"
- break
- fi
- done
-
- if [ "$found" = "yes" ]; then
- cryptsetup luksClose "$dst"
- else
- cryptsetup remove "$dst"
- fi
- return $?
- }
-
- load_optimized_module () {
- local module optmodule
- module="$1"
-
- optmodule=$(find "/lib/modules/$(uname -r)/kernel/arch" -name "${module}*.ko" 2> /dev/null)
- if [ -n "$optmodule" ] && [ "$(echo -n "$optmodule" | wc -l)" -eq 1 ]; then
- modprobe "$optmodule" 2>/dev/null && return 0
- fi
-
- modprobe "$module" 2>/dev/null || return 1
- return 0
- }
-
- # Sets up all entries in crypttab
- handle_crypttab_line_start () {
- dst=$1
- src=$2
- key=$3
- opts=$4
-
- # Make sure that all fields are present
- if [ -z "$dst" ]; then
- continue
- elif [ -z "$src" ] || [ -z "$key" ] || [ -z "$opts" ]; then
- device_msg "$dst" "skipped, missing parameters"
- continue
- fi
-
- # parse UUID= symlinks
- if [ "${src#UUID=}" != "$src" ]; then
- src="/dev/disk/by-uuid/${src#UUID=}"
- elif [ "${src#LABEL=}" != "$src" ]; then
- src="/dev/disk/by-label/${src#LABEL=}"
- fi
-
- # Do the preparatory steps
- if ! parse_opts "$opts"; then
- device_msg "$dst" "invalid opts"
- continue
- elif ! check_key; then
- device_msg "$dst" "invalid key"
- continue
- elif ! lo_setup; then
- device_msg "$dst" "loopback failed"
- fi
-
- # Ignore noauto devices
- if [ "$IGNORE" = "yes" ] && [ -z "$FORCE_START" ]; then
- device_msg "$dst" "ignored"
- continue
- fi
-
- # Make sure source device exists
- if [ ! -r "$src" ]; then
- if [ "$LOUD" = "yes" ]; then
- device_msg "$dst" "skipped, device $src does not exist"
- fi
- continue
- fi
-
- # Make sure that target device doesn't exist
- if [ -b "/dev/mapper/$dst" ]; then
- device_msg "$dst" "running"
- continue
- fi
-
- # All checks passed, do the real setup
- log_action_msg "$dst (starting)"
- result="ok"
- if [ "$USELUKS" = "yes" ]; then
- do_luks || result="fail"
- else
- do_noluks || result="fail"
- fi
-
- # Finish up
- if [ "$result" != "ok" ]; then
- rm_lo_setup
- device_msg "$dst" "failed"
- else
- do_swap
- do_tmp
- device_msg "$dst" "started"
- fi
-
- return 0
- }
-
- handle_crypttab_line_stop () {
- dst=$1
- src=$2
- key=$3
- opts=$4
-
- if [ ! -b "/dev/mapper/$dst" ]; then
- device_msg "$dst" "stopped"
- continue
- fi
-
- opencount=$(dmsetup info -c --noheadings -o open "$dst" 2> /dev/null || true)
- if [ -z "$opencount" ]; then
- device_msg "$dst" "error"
- continue
- elif [ "$opencount" != "0" ]; then
- device_msg "$dst" "busy"
- continue
- fi
-
- #major=$(dmsetup info -c --noheadings -o major "$dst" 2> /dev/null || true)
- #minor=$(dmsetup info -c --noheadings -o minor "$dst" 2> /dev/null || true)
- src_major=$(dmsetup deps "$dst" 2> /dev/null | sed -e 's/^.*(\([0-9]*\), [0-9]*)$/\1/g' || true)
- src_minor=$(dmsetup deps "$dst" 2> /dev/null | sed -e 's/^.*([0-9]*, \([0-9]*\))$/\1/g' || true)
-
- if [ -z "$src_major" ] || [ -z "$src_minor" ]; then
- device_msg "$dst" "error"
- continue
- fi
-
- do_close
-
- # Detach loopback device, if attached
- if [ "$src_major" = "7" ]; then
- loopdev="/dev/loop${src_minor}"
- if ! rm_lo_setup; then
- device_msg "$dst" "detaching loopback failed"
- continue
- fi
- fi
-
- device_msg "$dst" "stopping"
-
- return 0
- }
-
- do_start () {
- local dst src key opts result
-
- modprobe -qb dm-mod || true
- modprobe -qb dm-crypt || true
- dmsetup mknodes > /dev/null 2>&1 || true
- log_action_begin_msg "Starting $INITSTATE crypto disks"
- mount_fs
-
- egrep -v "^[[:space:]]*(#|$)" "$TABFILE" | while read dst src key opts; do
- handle_crypttab_line_start "$dst" "$src" "$key" "$opts" <&3
- done 3<&1
- umount_fs
-
- log_action_end_msg 0
- }
-
- # Removes all mappings in crypttab
- do_stop () {
- local dst src key opts opencount major minor loopmajor
-
- dmsetup mknodes
- log_action_begin_msg "Stopping $INITSTATE crypto disks"
- loopmajor=$(grep "[[:space:]]*loop$" /proc/devices | sed 's/^[[:space:]]*//;s/[[:space:]].*//')
-
- egrep -v "^[[:space:]]*(#|$)" "$TABFILE" | while read dst src key opts; do
- handle_crypttab_line_stop "$dst" "$src" "$key" "$opts" <&3
- done 3<&1
-
- log_action_end_msg 0
- }
-
- # Convenience function to handle $VERBOSE
- device_msg () {
- local dst msg
- dst="$1"
- msg="$2"
-
- if [ "$VERBOSE" != "no" ]; then
- log_action_cont_msg "$dst ($msg)"
- fi
- }
-